package net.xujialiang.XTestRPA.Service.Env;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import net.xujialiang.XTestRPA.Entity.Env.Relations.XRPAEnvAndEnvTag;
import net.xujialiang.XTestRPA.Entity.Env.XRPAEnv;
import net.xujialiang.XTestRPA.Entity.Tenant.XRPATenant;
import net.xujialiang.XTestRPA.Repository.Env.EnvAndEnvTagRepository;
import net.xujialiang.XTestRPA.Repository.Env.EnvRepository;
import net.xujialiang.XTestRPA.Repository.Tenant.TenantRepository;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.util.*;

@Service
public class XRPAEnvService {

    @Autowired
    EnvRepository envRepository;
    @Autowired
    TenantRepository tenantRepository;
    @Autowired
    EnvAndEnvTagRepository envAndEnvTagRepository;

    public void createEnv(Map<String, Object> reqData, String createAccount, String ttc) throws Exception {
        // 判断该租户是否已经达到环境数量上限
        long count = envRepository.countByTtc(ttc);
        Optional<XRPATenant> ret = tenantRepository.findByTtc(ttc);
        XRPATenant tenant = ret.get();
        long limit = tenant.getEnvLimit();
        if(count >= limit){
            throw new Exception("超过环境数限制");
        }

        String envName = (String) reqData.getOrDefault("envName", "");
        if(envName.equals("")){
            throw new Exception("环境名称不得为空");
        }
        String groupID = (String) reqData.getOrDefault("groupID", "");
        if(groupID.equals("")){
            throw new Exception("未选择分组");
        }
        ArrayList tagIDs = (ArrayList) reqData.getOrDefault("tagIDs", new ArrayList());
        String tagIDStr = "";
        for (Object tagID:tagIDs) {
            tagIDStr = tagIDStr + tagID.toString() + ",";
        }
        if(tagIDStr.length()>0){
            tagIDStr = tagIDStr.substring(0, tagIDStr.length()-1);
        }
        String url = (String) reqData.getOrDefault("url", "");
        String browser = (String) reqData.getOrDefault("browser", "Chrome");
        String browserVersion = (String) reqData.getOrDefault("browserVersion", "106");
        String os = (String) reqData.getOrDefault("os", "Mac");
        String cookie = (String) reqData.getOrDefault("cookie", "");
        String mark = (String) reqData.getOrDefault("mark", "");
        String userAgent = (String) reqData.getOrDefault("userAgent", "");
        String timeZone = (String) reqData.getOrDefault("timeZone", "+8");
        String webRTC = (String) reqData.getOrDefault("webRTC", "");
        String location = (String) reqData.getOrDefault("location", "Shanghai");
        String acceleration = (String) reqData.getOrDefault("acceleration", "");
        String language = (String) reqData.getOrDefault("language", "zh-CN");
        String canvas = (String) reqData.getOrDefault("canvas", "");
        String deviceName = (String) reqData.getOrDefault("deviceName", "");
        String resolution = (String) reqData.getOrDefault("resolution", "");
        String mac = (String) reqData.getOrDefault("mac", "");
        String webgl = (String) reqData.getOrDefault("webgl", "");
        String webGLCorp = (String) reqData.getOrDefault("webGLCorp", "");
        String webGLRender = (String) reqData.getOrDefault("webGLRender", "");
        String doNotTrack = (String) reqData.getOrDefault("doNotTrack", "");
        String audioContext = (String) reqData.getOrDefault("audioContext", "");
        String mediaDevice = (String) reqData.getOrDefault("mediaDevice", "");
        String speechVoice = (String) reqData.getOrDefault("speechVoice", "");
        String concurrent = (String) reqData.getOrDefault("concurrent", "");
        String mem = (String) reqData.getOrDefault("mem", "2");
        Integer mOrder = (Integer) reqData.getOrDefault("mOrder", 0);

        XRPAEnv entity = XRPAEnv.builder()
                .envID(UUID.randomUUID().toString())
                .envName(envName)
                .url(url)
                .groupID(groupID)
                .tagIDs(tagIDStr)
                .browser(browser)
                .browserVersion(browserVersion)
                .os(os)
                .cookie(cookie)
                .acceleration(acceleration)
                .audioContext(audioContext)
                .location(location)
                .mark(mark)
                .canvas(canvas)
                .concurrent(concurrent)
                .deviceName(deviceName)
                .doNotTrack(doNotTrack)
                .language(language)
                .mac(mac)
                .userAgent(userAgent)
                .webGLCorp(webGLCorp)
                .mediaDevice(mediaDevice)
                .mem(mem)
                .mOrder(mOrder)
                .resolution(resolution)
                .speechVoice(speechVoice)
                .timeZone(timeZone)
                .ttc(ttc)
                .webgl(webgl)
                .webRTC(webRTC)
                .webGLRender(webGLRender)
                .createAccount(createAccount)
                .createTime(new Timestamp(System.currentTimeMillis()))
                .build();
        envRepository.save(entity);

        List<XRPAEnvAndEnvTag> tags = new ArrayList<>();
        for (Object tagId: tagIDs) {
            XRPAEnvAndEnvTag e = XRPAEnvAndEnvTag.builder().envID(entity.getEnvID()).tagID((String) tagId).build();
            tags.add(e);
        }
        List<XRPAEnvAndEnvTag> existsData = envAndEnvTagRepository.findAllByEnvID(entity.getEnvID());
        envAndEnvTagRepository.deleteAll(existsData);
        envAndEnvTagRepository.saveAll(tags);
    }

    public void deleteEnv(int id, String ttc) throws Exception {
        Optional<XRPAEnv> entity = envRepository.findById(id);
        if(entity.isEmpty()){
            throw new Exception("未查询到环境");
        }else{
            XRPAEnv env = entity.get();
            // 判断是否是该分组所在租户
            if(env.getTtc().equals(ttc)){
                // 删除ENVTAG关联关系
                List<XRPAEnvAndEnvTag> relations = envAndEnvTagRepository.findAllByEnvID(env.getEnvID());
                envAndEnvTagRepository.deleteAll(relations);
                envRepository.delete(entity.get());
            }else{
                throw new Exception("无权限操作");
            }
        }
    }

    public Map<String, Object> fetchByPage(String groupId, String envName, List<String> tagIds, String ttc, int page, int pageSize) throws Exception {
        PageRequest pr =  PageRequest.of(page,pageSize);
        if(groupId.equals("")){
            groupId = null;
        }
        if(envName.equals("")){
            envName = null;
        }
        if(tagIds.size() == 0){
            tagIds = null;
        }

        Page<XRPAEnv> pageData = envRepository.findByEnvNameAndGroupIdAndByTagIds(groupId, envName, tagIds, ttc, pr);
        Map<String, Object> ret = new LinkedHashMap<>();
        ret.put("totalPages", pageData.getTotalPages());
        ret.put("totalCount", pageData.getTotalElements());
        ret.put("page", page);
        ret.put("pageSize", pageSize);
        ret.put("list", pageData.getContent());
        return ret;
    }

    public XRPAEnv fetchById(Integer id, String ttc) throws Exception {
        Optional<XRPAEnv> ret = envRepository.findByIdAndTtc(id, ttc);
        if(ret.isEmpty()){
            throw new Exception("未查询到环境信息");
        }else{
            return ret.get();
        }
    }

    public XRPAEnv fetchByEnvID(String envID, String ttc) throws Exception {
        Optional<XRPAEnv> ret = envRepository.findByEnvIDAndTtc(envID, ttc);
        if(ret.isEmpty()){
            throw new Exception("未查询到环境信息");
        }else{
            return ret.get();
        }
    }

    public void update(Map<String, Object> reqData, String ttc) throws Exception {
        Integer id = (Integer) reqData.get("id");
        Optional<XRPAEnv> ret = envRepository.findById(id);
        if(ret.isEmpty()){
            throw new Exception("未查询到环境信息");
        }else{
            XRPAEnv entity = ret.get();
            if(entity.getTtc().equals(ttc)){
                String envName = (String) reqData.get("envName");
                if(envName != null){
                    entity.setEnvName(envName);
                }
                String groupId = (String) reqData.get("groupID");
                if(groupId != null){
                    entity.setGroupID(groupId);
                }
                ArrayList tagIDs = (ArrayList) reqData.get("tagIDs");
                if(tagIDs!=null && tagIDs.size()>0){
                    String tagIDStr = "";
                    for (Object tagID:tagIDs) {
                        tagIDStr = tagIDStr + tagID.toString() + ",";
                    }
                    tagIDStr = tagIDStr.substring(0, tagIDStr.length()-1);
                    entity.setTagIDs(tagIDStr);
                }
                String url = (String) reqData.get("url");
                if(url != null){
                    entity.setUrl(url);
                }
                String browser = (String) reqData.get("browser");
                if(browser != null){
                    entity.setBrowser(browser);
                }
                String browserVersion = (String) reqData.get("browserVersion" );
                if(browserVersion != null){
                    entity.setBrowserVersion(browserVersion);
                }
                String os = (String) reqData.get("os");
                if(os != null){
                    entity.setOs(os);
                }
                String cookie = (String) reqData.get("cookie");
                if(cookie != null){
                    entity.setCookie(cookie);
                }
                String mark = (String) reqData.get("mark");
                if(mark != null){
                    entity.setMark(mark);
                }
                String userAgent = (String) reqData.get("userAgent");
                if(userAgent != null){
                    entity.setUserAgent(userAgent);
                }
                String timeZone = (String) reqData.get("timeZone");
                if(timeZone != null){
                    entity.setTimeZone(timeZone);
                }
                String webRTC = (String) reqData.get("webRTC");
                if(webRTC != null){
                    entity.setWebRTC(webRTC);
                }
                String location = (String) reqData.get("location");
                if(location != null){
                    entity.setLocation(location);
                }
                String acceleration = (String) reqData.get("acceleration");
                if(acceleration != null){
                    entity.setAcceleration(acceleration);
                }
                String language = (String) reqData.get("language");
                if(language != null){
                    entity.setLanguage(language);
                }
                String canvas = (String) reqData.get("canvas");
                if(canvas != null){
                    entity.setCanvas(canvas);
                }
                String deviceName = (String) reqData.get("deviceName");
                if(deviceName != null){
                    entity.setDeviceName(deviceName);
                }
                String resolution = (String) reqData.get("resolution");
                if(resolution != null){
                    entity.setResolution(resolution);
                }
                String mac = (String) reqData.get("mac");
                if(mac != null){
                    entity.setMac(mac);
                }
                String macEnable = (String) reqData.get("macEnable");
                if(macEnable != null){
                    entity.setMacEnable(macEnable);
                }
                String webgl = (String) reqData.get("webgl");
                if(webgl != null){
                    entity.setWebgl(webgl);
                }
                String webglMetaEnable = (String) reqData.get("webglMetaEnable");
                if(webglMetaEnable != null){
                    entity.setWebglMetaEnable(webglMetaEnable);
                }
                String webGLCorp = (String) reqData.get("webGLCorp");
                if(webGLCorp != null){
                    entity.setWebGLCorp(webGLCorp);
                }
                String webGLRender = (String) reqData.get("webGLRender");
                if(webGLRender != null){
                    entity.setWebGLRender(webGLRender);
                }
                String doNotTrack = (String) reqData.get("doNotTrack");
                if(doNotTrack != null){
                    entity.setDoNotTrack(doNotTrack);
                }
                String audioContext = (String) reqData.get("audioContext");
                if(audioContext != null){
                    entity.setAudioContext(audioContext);
                }
                String mediaDevice = (String) reqData.get("mediaDevice");
                if(mediaDevice != null){
                    entity.setMediaDevice(mediaDevice);
                }
                String speechVoice = (String) reqData.get("speechVoice");
                if(speechVoice != null){
                    entity.setSpeechVoice(speechVoice);
                }
                String concurrent = (String) reqData.get("concurrent");
                if(concurrent != null){
                    entity.setConcurrent(concurrent);
                }
                String mem = (String) reqData.get("mem");
                if(mem != null){
                    entity.setMem(mem);
                }
                Integer mOrder = (Integer) reqData.get("mOrder");
                if(mOrder != null){
                    entity.setMOrder(mOrder);
                }
                envRepository.save(entity);

                // 创建标签的关联关系
                List<XRPAEnvAndEnvTag> tags = new ArrayList<>();
                for (Object tagId: tagIDs) {
                    XRPAEnvAndEnvTag e = XRPAEnvAndEnvTag.builder().envID(entity.getEnvID()).tagID((String) tagId).build();
                    tags.add(e);
                }
                List<XRPAEnvAndEnvTag> existsData = envAndEnvTagRepository.findAllByEnvID(entity.getEnvID());
                envAndEnvTagRepository.deleteAll(existsData);
                envAndEnvTagRepository.saveAll(tags);

            }else{
                throw new Exception("无权限操作");
            }
        }
    }

    public void updateEnvOrder(Map<Integer, Integer> newOrders, String ttc) throws Exception {
        Object[] ids = newOrders.keySet().toArray();
        Arrays.stream(ids).mapToInt(t-> (int) t);
        ArrayList<Integer> list = new ArrayList(Arrays.asList(ids));

        List<XRPAEnv> envs = (List<XRPAEnv>) envRepository.findAllById(list);

        boolean noPermission = false;
        for (int i = 0; i < envs.size(); i++) {
            XRPAEnv group = envs.get(i);
            if(group.getTtc().equals(ttc)){
                Integer newOrder = newOrders.get(group.getId());
                group.setMOrder(newOrder);
            }else{
                noPermission= true;
            }
        }
        if(noPermission) {
            throw new Exception("无权限操作");
        }else{
            envRepository.saveAll(envs);
        }
    }

    public void importData(MultipartFile multipartFile, String groupID, String ttc) throws Exception {
        // 获取原始名字
        String fileName = multipartFile.getOriginalFilename();
        // 获取后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        //先将.json文件转为字符串类型
        UUID uuid = UUID.randomUUID();
        File file = new File("./tmp/"+ uuid+".json");
        //将MultipartFile类型转换为File类型
        FileUtils.copyInputStreamToFile(multipartFile.getInputStream(),file);
        String jsonString = FileUtils.readFileToString(file, "UTF-8");
        //如果是json或者txt文件
        if (".json".equals(suffixName)) {
            //再将json字符串转为实体类
            JsonObject obj =  new Gson().fromJson(jsonString, JsonObject.class);
            JsonArray envJsonArray = (JsonArray) obj.get("EnvList");
            Type listType = new TypeToken<ArrayList<XRPAEnv>>(){}.getType();
            List<XRPAEnv> envList = new Gson().fromJson(envJsonArray, listType);
            for (XRPAEnv entity : envList) {
                entity.setEnvID(UUID.randomUUID().toString());
                entity.setId(null);
                entity.setGroupID(groupID);
                entity.setTtc(ttc);
            }

            envRepository.saveAll(envList);

        } else {
            throw new Exception("请上传正确格式的json");
        }
    }

    public List<XRPAEnv> exportData(Map<String, Object> reqData, String ttc){
        List<Integer> envIds = (List<Integer>) reqData.get("ids");
        if(envIds != null && envIds.size()>0){
            // 导出指定的环境
            return (List<XRPAEnv>) envRepository.findAllById(envIds);
        }else{
            //导出所有环境
            return envRepository.findAllByTtc(ttc);
        }
    }

}